<?php
/**
 * 图像验证码类
 * 2019年10月31日09:48:13
 * ZJY
 */
namespace phpless\ORG;

class ImageCoder
{
    // === 相关属性 ===
    // 图像宽
    public $width = 150;
    // 图像高
    public $height = 40;
    // 图像背景色 默认为随机
    public $background_color = '';
    // 渲染字体大小
    public $font_size = 5;
    // 渲染文字个数
    public $font_number = 4;
    // 渲染字体颜色、干扰线颜色、干扰像素点颜色
    public $font_color = '0,0,0';
    // 干扰线的风格或高度 1
    public $line_style = 10;
    // 干扰像素点个数
    public $pixel_number = 777;
    // 验证码字典 排除易混淆字符串 012lozIOZ
    private $code_data = '3456789abcdefghijkmnpqrstuvwxyABCDEFGHJKLMNPQRSTUVWXY';
    // 图片资源
    public $image_source;

    // 构造函数 初始化数据：width 、 height 、 background_color 、 font_size 、 font_number 、 font_color
    public function __construct($config=[])
    {
        $this -> width = isset($config['width'])?$config['width']:$this -> width;
        $this -> height = isset($config['height'])?$config['height']:$this -> height;
        $this -> font_size = isset($config['font_size'])?$config['font_size']:$this -> font_size;
        $this -> font_number = isset($config['font_number'])?$config['font_number']:$this -> font_number;
        $this -> font_color = isset($config['font_color'])?$config['font_color']:$this -> font_color;
        $this -> pixel_number = isset($config['pixel_number'])?$config['pixel_number']:$this -> pixel_number;
        $this -> background_color = isset($config['background_color'])?$config['background_color']:$this -> background_color;
        $this -> width = isset($config['width'])?$config['width']:$this -> width;
    }
    // 创建图片资源
    public function createImageSource()
    {
        $this -> image_source = imageCreateTrueColor($this -> width, $this-> height);
        return $this;
    }
    // 提取颜色值
    public function getColor($color)
    {
        $result = [];
        $color = explode(',', $color);
        $result['red'] = isset($color[0])?(int)$color[0]:mt_rand(0,255);
        $result['green'] = isset($color[1])?(int)$color[1]:mt_rand(0,255);
        $result['blue'] = isset($color[2])?(int)$color[2]:mt_rand(0,255);
        return $result;
    }
    // 填充图片资源背景颜色
    public function fillBackgroundColor()
    {
        $background_color = $this -> getColor($this -> background_color);
        // 分配颜色
        $allocate_color = imageColorAllocate($this -> image_source, $background_color['red'], $background_color['green'], $background_color['blue']);
        // 填充颜色
        imageFill($this -> image_source, 0, 0, $allocate_color);
        return $this;
    }
    // 添加像素点干扰
    public function pixelMix()
    {
        for($i = 0; $i < $this -> pixel_number; $i++){
            $allocate_color = imageColorAllocate($this -> image_source, mt_rand(0, 255), mt_rand(0, 255), mt_rand(0, 255));
            imageSetPixel($this -> image_source, mt_rand(1, $this -> width - 2), mt_rand(1, $this -> height - 2), $allocate_color);
        }
        return $this;
    }
    // 添加直线干扰
    public function lineMix()
    {
        // 干扰线风格
        $line_style = min($this -> line_style,$this -> height / 2);
        // 直线对角坐标
        $start_x = 0;
        $start_y = $this -> height / 2 - $line_style;
        $end_x = $this -> width;
        $end_y = $this -> height / 2 + $line_style;
        $allocate_color = imageColorAllocate($this -> image_source, mt_rand(0, 255), mt_rand(0, 255), mt_rand(0, 255));
        imageFilledRectangle($this -> image_source, $start_x, $start_y, $end_x, $end_y, $allocate_color);
        return $this;
    }
    // 生成验证码 渲染字符串
    public function createCode()
    {
        $font_size = $this -> font_size;
        $font_size_height = 14;
        $font_number = $this -> font_number;
        $new_code_data=str_shuffle($this -> code_data);
        $image_code = '';
        $set_image_code = ''; 
        for($i = 0; $i < $font_number; $i++ ){
            $image_code=$image_code.$new_code_data[$i];
            $set_image_code = $set_image_code.'  '.$new_code_data[$i]; 
        }
        $set_image_code = trim($set_image_code);
        $filled_number = $font_number * 2 - 1;
        $start_x = ($this -> width - $font_size_height * $filled_number) / 2;
        $start_y = ($this -> height - $font_size_height) / 2;
        // === 字体颜色 ===
        $font_color = $this -> getColor($this -> font_color);
        $allocate_color = imageColorAllocate($this -> image_source, $font_color['red'], $font_color['green'], $font_color['blue']);
        imageString($this -> image_source, $font_size, $start_x, $start_y, $set_image_code, $allocate_color);
        // 储存到 SESSION 中
        $_SESSION['image_code'] = $image_code;
        return $this;
    }
    // 渲染图像验证码 直接输出
    public function outputCode()
    {
        // 链式操作，生成图片验证码
        $result = $this -> createImageSource() -> fillBackgroundColor() -> pixelMix() -> lineMix() -> createCode();
        // 输出图像
        header('Content-type:image/png');
        imagePng($result -> image_source);
    }
    // 获取验证码
    static function getCode()
    {
        return isset($_SESSION['image_code'])?$_SESSION['image_code']:null;
    }
    // 检验图像验证码
    static function verifyCode($image_code=null)
    {
        $result = false;
        if(empty($image_code) || !is_string($image_code)){
            return $result;
        }
        $session_image_code = isset($_SESSION['image_code'])?$_SESSION['image_code']:'';
        return trim(strtoupper($session_image_code)) === trim(strtoupper($image_code));
    }
}
